<?php
// FIXME: should be abstract?
/**
 * Represents object model, e.g. News, User.
 * Allows to: 
 *  - manage object - seting and getting it's data,
 *  - save - store object in database table using proper mapper.
 * 
 * @author Damian Sromek <damianpaq@gmail.com>
 * @version 0.1
 */
abstract class Plus_Model_Model_DbTable_Abstract extends Plus_Model_Model_Abstract
{
	/**
	 * Unique identifier of object.
	 * @var int/mixed
	 */
	protected $_id = '';
	
	/**
	 * Name of the variable name used as the uniqe identifier of the model's object 
	 * @var string
	 */
	protected $_idName = '_id';
	
	/**
	 * array (
	 * 		'variableName' => 'table_column_name'
	 * )
	 * @var array association array with names of data filed in the table
	 */
	protected $_tableColumns;
	
	/**
	 * Creates model using passed data and mapper.
	 * If in $options param is 'id' field but no 'idName' then it's used as value for 
	 * $this->_idName.
	 * @param $options array(
	 * 		'id' => '34',
	 * 		'idName' => 'id_user',
	 * 		'name' => 'ccv'
	 * )
	 * @param $mapper
	 * @return void
	 */
	public function __construct(array $options = array(), $mapper)
	{
		parent::__construct($options, $mapper);
		
		if (isset($options['idName'])) {
			$this->setIdName($options['idName']);
		} elseif (isset($options['id'])) {
			$this->setIdName($options['id']);
		}
	}
	
	/**
	 * Sets mapper used by this model.
	 * @param $mapper mapper we want to use by this model
	 * @return $this
	 * @throws Exception if mapper we want to use is instance of inproper class
	 * (non-PHPdoc)
	 * @see application/models/Model/Plus_Model_Model_Abstract#setMapper()
	 */
	public function setMapper($mapper)
	{
		if ($mapper === null || !$mapper instanceof Plus_Model_Mapper_DbTable_Abstract) {
			throw new Exception('DbTableMapper required');
		}
		return parent::setMapper($mapper);
	}	
	
	/**
	 * 
	 * @param $id country id
	 * @return $this
	 */
	public function setId($id)
	{
		$idName = $this->getIdName();
		$this->$idName = (int) $id;	
		
		return $this;
	}
	
	/**
	 * 
	 * @return int country id
	 */
	public function getId()
	{
		$idName = $this->getIdName();
		return $this->$idName;
	}
	
	/**
	 * 
	 * @return name of the variable used as id of the object
	 */
	public function getIdName()
	{
		//$this->_log->info(get_class($this) . ' - idName = ' . $this->_idName);
		return $this->_idName;
	}
	
	/**
	 * 
	 * @param $idName name of the variable used as id of the object
	 * @return $this
	 */
	protected function setIdName($idName)
	{
		$this->_idName = $idName;
		return $this;
	}
	
	public function getIdColumn()
	{
		return $this->_tableColumns[$this->getIdName()];
	}
	
	/**
	 * array (
	 * 		'variableName' => 'table_column_name'
	 * )
	 * @return array association array with names of data filed in the table
	 */
	public function getTableCollumns()
	{
		return $this->_tableColumns;
	}
	
	/**
	 * Adds information about this model protected variable used to store data,
	 * table columns wich represents variable value in database
	 * and getter/setter method postfix which allows to get/set that variable 
	 * from the outside.
	 * If $methodPostfix parameter is = null then as the postfix we use the $variableName.
	 * @param $variableName name of the protected variable
	 * @param $tableColumn name of the database table column wich stores passed variable name 
	 * @param $methodPostfix getter/setter method postfix
	 * @return $this
	 * (non-PHPdoc)
	 * @see application/models/Model/Plus_Model_Model_Abstract#addVar()
	 */
	protected function addVar($variableName, $tableColumn = null, $getMethod = null)
	{
		parent::addVar($variableName, $getMethod);
		$this->_tableColumns[$variableName] = 
			($tableColumn !== null) ? $tableColumn : $variableName;
		return $this;
	}
	
	/**
	 * Finds model with specified id using data mapper and puts it's data value
	 * into this object.
	 * @param $id id of searched model
	 * @return found object or null if object with such id doesn't exist
	 */
	public function find($id)
	{
		return $this->getMapper()->find($id);
	}
	
	public function get($id)
	{
		return $this->getMapper()->get($id);
	}
	
	/**
	 * Fetches all models from database table using mapper and returns them 
	 * as the array
	 * @return array array of objects fetched from database table
	 */
	public function fetchAll()
	{
		return $this->getMapper()->fetchAll();
	}
	
	/**
	 * @return array Association array with column names and their values of this object
	 * array ('column_name' => 'value')
	 */
	public function getTableDataArray()
	{
		$data = array();
		$tmpMethod = '';
		foreach ($this->_tableColumns as $variableName => $columnName) {
			$tmpMethod = 'get' . $this->_descriptionVariables[$variableName];
			$this->_log->info(get_class($this) . ' - trying execute - ' . $tmpMethod . "()");
			$data[$columnName] = $this->$tmpMethod();
		}
		return $data;
	}
	
	/**
	 * Sets models data getting them from row data - e.g. directly from database.
	 * @param $rowData array with row data, according to $_tableColumns information
	 * @return $this
	 */
	public function setOptionsFromRow($rowData)
	{
		$tmpMethod = '';
		$this->_log->info(get_class($this) . ' - setting data from row');
		foreach ($this->_tableColumns as $variableName => $columnName) {
			$tmpMethod = 'set' . $this->_descriptionVariables[$variableName];
			//$this->_log->info(get_class($this) . " - $tmpMethod()");
			
			$this->$tmpMethod($rowData->$columnName);
		}
		return $this;
	}
	
	/**
	 * (non-PHPdoc)
	 * @see application/models/Model/Plus_Model_Model_Abstract#delete()
	 */
	public function delete()
	{
		if ($this->getMapper() !== null) {
			$this->getMapper()->delete($this);
			$this->setId('');
		}
	}
}